﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Reflection;
using System.IO;
using System.Text.RegularExpressions;
using System.Collections;
using Org.Eurekaa.DNJ.Config;
using Org.Eurekaa.DNJ.Helpers;

namespace Org.Eurekaa.DNJ.http
{
    public class DNJHttpHandler : IHttpHandler
    {

        #region IHttpHandler Members

        public bool IsReusable
        {
            get { return false; }
        }

        private string GetScriptResource(Assembly assembly, string resourceName)
        {
            if (assembly == null) return "";
            
            Stream stream = assembly.GetManifestResourceStream(resourceName);
            if (stream == null) return "";

            StreamReader streamReader = new StreamReader(stream);
            
            string res = streamReader.ReadToEnd();
            streamReader.Close();
            stream.Close();
            return res;
        }
        private List<string> ParseUIResources(string qsLoad)
        {
            List<string> resList = new List<string>();

            Hashtable jqResDep;
            ResourcesConfig.LoadConfig("Org.Eurekaa.DNJ", "Resources.ResourceConfig.xml");
            ResourcesConfig.LoadConfig("Org.Eurekaa.DNJ.UI", "Resources.ResourceConfig.xml");
            ResourcesConfig.LoadConfig("Org.Eurekaa.DNJ.Ext", "Resources.ResourceConfig.xml");
            jqResDep = ResourcesConfig.Resources;

            

            #region (deprecated) 
            //jqResDep["jquery"] = "Org.Eurekaa.DNJ.Resources.jquery-1.3.2.min.js";
            //jqResDep["cookie"] = "Org.Eurekaa.DNJ.Resources.jquery.cookie.js";
            
            //jqResDep["ui.core"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.core.min.js";
            //jqResDep["ui.themes"] = "Org.Eurekaa.DNJ.UI.Resources.js.jquery.themeswitcher.js";

            //jqResDep["ui.draggable"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.draggable.min.js";
            //jqResDep["ui.droppable"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.droppable.min.js";
            //jqResDep["ui.resizable"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.resizable.min.js";
            //jqResDep["ui.selectable"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.selectable.min.js";
            //jqResDep["ui.sortable"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.sortable.min.js";

            //jqResDep["fx.core"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.core.min.js";
            //jqResDep["fx.blind"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.blind.min.js";
            //jqResDep["fx.bounce"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.bounce.min.js";
            //jqResDep["fx.clip"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.clip.min.js";
            //jqResDep["fx.drop"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.drop.min.js";
            //jqResDep["fx.explode"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.explode.min.js";
            //jqResDep["fx.fold"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.fold.min.js";
            //jqResDep["fx.highlight"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.highlight.min.js";
            //jqResDep["fx.pulsate"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.pulsate.min.js";
            //jqResDep["fx.scale"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.scale.min.js";
            //jqResDep["fx.shake"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.shake.min.js";
            //jqResDep["fx.slide"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.slide.min.js";
            //jqResDep["fx.transfer"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.effects.transfer.min.js";

            //jqResDep["ui.accordion"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.accordion.min.js";
            //jqResDep["ui.datepicker"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.datepicker.min.js";
            //jqResDep["ui.dialog"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.dialog.min.js";
            //jqResDep["ui.progressbar"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.progressbar.min.js";
            //jqResDep["ui.slider"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.slider.min.js";
            //jqResDep["ui.tabs"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.ui.tabs.min.js";

            //jqResDep["i18n"] = "Org.Eurekaa.DNJ.UI.Resources.js.ui.jquery-ui-i18n.min.js";
            #endregion


            MatchCollection listmc = Regex.Matches(qsLoad, @"([^,\[]+(\[[^\]]+\]){0,1}),{0,1}", RegexOptions.Compiled | RegexOptions.ECMAScript | RegexOptions.IgnoreCase | RegexOptions.Multiline );
            
            foreach (Match m in listmc)
            {
                string gval = m.Groups[1].Value;
                MatchCollection resmc = Regex.Matches(gval, @"([^,\[]+)\[([^\]]+)\]", RegexOptions.Compiled | RegexOptions.ECMAScript | RegexOptions.IgnoreCase | RegexOptions.Multiline);
                if (resmc.Count > 0)
                {
                    string parent = resmc[0].Groups[1].Value;
                    string children = resmc[0].Groups[2].Value;
                    if (jqResDep[parent + ".core"] != null)
                    {
                        resList.Add(jqResDep[parent + ".core"].ToString());
                        if (children.Equals("all"))
                        {
                            ArrayList res = new ArrayList(jqResDep.Values);
                            res.Sort();
                            foreach (DNJResource r in res)
                            {
                                if (r.ID.Contains(parent + ".")) resList.Add(r.ToString());
                            }
                            //foreach (string key in jqResDep.Keys)
                            //{
                            //    if (key.StartsWith(parent + ".")) resList.Add(jqResDep[key].ToString());
                            //}
                        }
                        else
                        {
                            string[] tokens = children.Split(',');
                            for (int i = 0; i < tokens.Length; i++)
                            {
                                if (jqResDep.ContainsKey(parent + "." + tokens[i])) resList.Add(jqResDep[parent + "." + tokens[i]].ToString());
                            }
                        }
                    }
                }
                else
                {
                    foreach (string key in jqResDep.Keys)
                    {
                        if (key.StartsWith(gval + ".") || key.Equals(gval)) resList.Add(jqResDep[key].ToString());
                    }
                }

            }

            //Performance comparison between regex parse and loops with substring.
            //"jqeury,cookie,fx[all],widgets[all],intercations[all]";
            //string[] tokens = qsLoad.ToLower().Split(',');
            //for (int i = 0; i < tokens.Length; i++)
            //{
            //    if (tokens[i].EndsWith("]") && (tokens[i].StartsWith("fx[") || tokens[i].StartsWith("fx[") || tokens[i].StartsWith("fx[")))
            //    {
            //        string elt = tokens[i].Substring(tokens[i].IndexOf("[") + 1).TrimEnd(new char[] { ']' });                    
            //        resList.AddRange(elt.Split(','));
            //    }
            //}
            return resList;
        }
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/javascript";
            if (HttpContext.Current.Request.HttpMethod.ToUpper().Equals("GET"))
            {
                StringBuilder sbScript = new StringBuilder();

                Assembly assembly = Assembly.GetExecutingAssembly();
                Assembly uiAssembly = Assembly.Load("Org.Eurekaa.DNJ.UI");
                Assembly extAssembly = Assembly.Load("Org.Eurekaa.DNJ.Ext");

                if (!string.IsNullOrEmpty(context.Request.QueryString["load"]))
                {
                    List<string> resources = ParseUIResources(context.Request.QueryString["load"]);

                    foreach (string resourceId in resources)
                    {
                        if (resourceId.StartsWith("Org.Eurekaa.DNJ.UI."))
                            sbScript.Append(GetScriptResource(uiAssembly, resourceId));
                        else if (resourceId.StartsWith("Org.Eurekaa.DNJ.Ext."))
                            sbScript.Append(GetScriptResource(extAssembly, resourceId));
                        else
                            sbScript.Append(GetScriptResource(assembly, resourceId));
                    }

                    sbScript.Append(GetScriptResource(assembly, "Org.Eurekaa.DNJ.Resources.jquery.dnj.js"));
                }

                if (!string.IsNullOrEmpty(context.Request.QueryString["conf"]))
                {
                    sbScript.Append(DNJ.RPC.RPCProcess.ScriptGenerator(context));                    
                }



                #if DEBUG
                    string generatedScript = sbScript.ToString();
                #else
                    DNJ.Helpers.JavaScriptMinifier jsmin = new DNJ.Helpers.JavaScriptMinifier();                                
                    string generatedScript = jsmin.Minify(sbScript.ToString());                    
                #endif

                context.Response.Write(generatedScript);

            }
            else
                DNJ.RPC.RPCProcess.InvokerProcess(context);

                

        }

        #endregion
    }
}
